import deepClone from '@/libs/deepClone'
import router from '@/router'
import dayjs from 'dayjs'
import {clearStorage, getStorage, setStorage} from './localstoreage'
import {clearSession} from './sessionStorage'

/**
 * 登出
 */
export function logout() {
  clearStorage()
  clearSession()
  location.reload()
}

/**检测数据类型 */
export function checkDataType(val: any) {
  if (Array.isArray(val)) {
    return 'array'
  } else if (val instanceof Object) {
    return 'object'
  } else if (typeof val === 'string') {
    return 'string'
  } else if (typeof val === 'number') {
    return 'number'
  } else {
    if (val === null) {
      return null
    } else if (val === undefined) {
      return undefined
    }
  }
}

/**复杂数据递归查询所有属性 */
export function checkComplexDataw(data: any, cb?: Function) {
  if (typeof data === 'string') return
  // 控制跳出闭包
  let flag = true

  // 对应属性所属对象/数组的key值列表/下标列表
  let keyList: any[] = []

  loop(data)

  function loop(loopData: any) {
    let defaultKeyListLength = keyList.length
    if (!flag) return
    if (checkDataType(loopData) === 'array') {
      let copyData = loopData.flat(Infinity)
      let currentIdx = keyList.length
      for (let i = 0; i < copyData.length; i++) {
        if (keyList.length > currentIdx) {
          keyList = keyList.slice(0, currentIdx)
          keyList[currentIdx] = i
        } else {
          keyList.push(i)
        }
        loop(copyData[i])
      }
      keyList.splice(keyList.length - 1, 1)
    } else if (checkDataType(loopData) === 'object') {
      for (const key in loopData) {
        keyList.push(key)
        loop(loopData[key])
      }
      keyList.splice(keyList.length - 1, 1)
    } else {
      if (cb && typeof cb === 'function') {
        let returnData = cb(loopData, keyList)
        keyList.splice(keyList.length - 1, 1)
        flag = returnData === false ? false : true
      }
    }
  }
}

/**
 * 判断val是否是null、undefined、N/A中的一种
 *
 * @param val : any
 *
 * @returns boolean:true是空数据，false不是空数据
 */
export function isNull(val: any) {
  return (val ?? null) === null || val !== val
}

/**
 * 对象非空校验，检查数据内是否包含null或者undefined
 * @param data
 * @returns boolean：true表示对象中有null或者undefined
 */
export function checkEmpty(data: any) {
  let flag = false
  checkComplexDataw(data, (loopData: any) => {
    if (!isNull(loopData)) {
      flag = true
      return false
    }
  })
  return flag
}

/**
 * 树形结构数据递归查询所有子项
 * @param target
 * @param childrenKey
 * @param cb
 * @returns
 */

export function treeMap<T extends {[key: string]: any}>(
  target: T[] | T,
  childrenKey: keyof T,
  cb?: (data: T) => boolean
): any {
  if (Array.isArray(target)) {
    for (let i = 0; i < target.length; i++) {
      const data = target[i]
      if (typeof cb === 'function') {
        let bol = cb(data)
        if (bol) return true
      }
      // treeMap继续递归当前项
      let bol = treeMap(data, childrenKey, cb)
      if (bol) return true
    }
  } else if (target instanceof Object) {
    // 存在子项时
    if (Array.isArray(target[childrenKey]) && target[childrenKey].length) {
      let bol = treeMap(target[childrenKey], childrenKey, cb)
      if (bol) return true
    }
  }
}

/**去除多余回车,制表符(tab)等 */
export function removeStrInvaildSymb(data: string) {
  return checkDataType(data) === 'string' ? data.trim().replace(/\n|\t/g, '') : data
}

/**判断是否是URL字符串 */
export function IsURL(str_url: string): Boolean {
  var v = new RegExp(
    '^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$',
    'i'
  )
  return v.test(str_url)
}

/**根据文件流下载文件 */
export async function downFile(blobOfFile: Blob, fileName?: string, extension?: string) {
  let a_link = document.createElement('a')
  // // 这里是将url转成blob地址，
  // let res = await fetch(link, { mode: 'no-cors' })
  // console.log(res)
  // let blob = await(res as Response).blob()
  // console.log(blob)
  // if (!blob.type)
  //   return message.error({
  //     message: '提示',
  //     description: '文件下载失败',
  //   })
  // let blobAB = await blobOfFile.arrayBuffer()
  // let blob = new Blob(blobAB, { type: blobOfFile.type })
  // 将链接地址字符内容转变成blob地址

  if (blobOfFile.size === 0) {
    console.error('暂无数据可下载')
    return
  }

  console.log(fileName)

  let nowTiem: string = dayjs().format('YYYYMMDDHHmmss')

  let filename = ''

  // if (fileName) filename = fileName + '_' + nowTiem
  if (fileName) filename = fileName

  if (extension) filename = filename + '.' + extension

  if ('download' in a_link) {
    a_link.style.display = 'none'
    a_link.href = URL.createObjectURL(blobOfFile)
    a_link.download = filename || nowTiem //下载的文件的名字
    document.body.appendChild(a_link)
    a_link.click()
    document.body.removeChild(a_link)
  } else {
    // IE10+下载
    // window.navigator.msSaveBlob(blob, fileName)
    alert('请使用IE浏览器以外的浏览器进行下载！')
  }
}

/**下拉选择输入关键字筛选 */
export const filterOption = (input: string, option: any, target?: string) => {
  return option[target || 'label'].toLowerCase().indexOf(input.toLowerCase()) >= 0
}

/**判断元素滚动到父元素底部 */
export const domIsScrollBottom = (parentId: string): Boolean => {
  let scrollHeight = document.getElementById(parentId)?.scrollHeight as number
  let offsetHeight = document.getElementById(parentId)?.offsetHeight as number
  let scrollTop = document.getElementById(parentId)?.scrollTop as number
  let diffHeight = scrollHeight - (offsetHeight + scrollTop)
  if (diffHeight <= 10) {
    return true
  } else {
    return false
  }
}

/**
 *
 * @param eventTypeName 事件类型名称
 * @returns
 */
export const eventTypeName2ImageName = (eventTypeName: string): string => {
  switch (eventTypeName) {
    case '设备离线':
      return 'device-offline'
    case '设备上线':
      return 'device-success'
    case '设备故障':
      return 'device-fault'
    default:
      return 'device-normal'
  }
}

/**
 * 根据px值转为rem
 * @param px px值
 * @returns
 */
export const px2rem = (px: number) => {
  const rootFontSize = getComputedStyle(document.documentElement).fontSize.split('px')[0]
  return px / Number(rootFontSize)
}

/**
 * 设置页面根字体
 */
export const setWindowRootFontSize = () => {
  const currentWidth = getComputedStyle(document.documentElement).width.split('px')[0]
  const scale = Number(currentWidth) / 1920
  document.documentElement.style.fontSize = scale * 16 + 'px'
}

/**
 * echart图表tooltip自定义html
 *
 * @desc series中的data为多维数组时，请将value放在最后一维中，此处判断series.data为数组时，取的最后一维当value展示
 */
export function coustomEchartTooltip(
  params: any,
  data?: {
    contentTitle?: string
    contentLeftText?: string
    contentValueUnit?: string
    contentLeftTextKey?: string
  }
) {
  let {contentLeftText, contentLeftTextKey, contentTitle, contentValueUnit} = Object.assign(
    {},
    data
  )

  let tooltip = document.createElement('div')
  tooltip.className = 'tooltip'

  let blurMask = document.createElement('div')
  blurMask.className = 'tooltip-blurMask'
  tooltip.appendChild(blurMask)

  let title = document.createElement('p')
  title.className = 'noHanzi tooltip-title'
  title.innerText =
    (contentTitle ?? null) === null ? params.map((param: any) => param.name) : contentTitle
  tooltip.appendChild(title)

  if (Array.isArray(params)) {
    for (let i = 0; i < params.length; i++) {
      const param = params[i]

      let name = param.name

      let value =
        (Array.isArray(param.value) ? Math.abs(param.value.slice(-1)[0]) : Math.abs(param.value)) +
        (contentValueUnit || '')

      let content = document.createElement('div')
      content.className = 'tooltip-content'

      let contentLeft = document.createElement('span')
      contentLeft.className = 'hanzi contentLeft'

      contentLeft.innerText = param.data.toolTipConentLeftText || contentLeftText || name

      let contentRight = document.createElement('span')
      contentRight.className = 'noHanzi contentRight'
      contentRight.innerText = value

      content.appendChild(contentLeft)
      content.appendChild(contentRight)

      i !== params.length - 1 && (content.style.marginBottom = '8px')
      tooltip.appendChild(content)
    }
  } else {
    let name = params.name
    let value = params.value + (contentValueUnit || '')

    let content = document.createElement('div')
    content.className = 'tooltip-content'

    let contentLeft = document.createElement('span')
    contentLeft.className = 'hanzi contentLeft'
    contentLeft.innerText = contentLeftText || name

    let contentRight = document.createElement('span')
    contentRight.className = 'noHanzi contentRight'
    contentRight.innerText = value

    content.appendChild(contentLeft)
    content.appendChild(contentRight)

    tooltip.appendChild(content)
  }
  return tooltip
}

/**
 *
 * @param  data 省市区
 * @returns 返回组合后的省市区
 */
export function addressJoin({
  province,
  city,
  district,
  separator = '-',
  defaultAddress = '暂未设置地址'
}: {
  province: string
  city: string
  district: string
  separator?: string
  defaultAddress?: string
}) {
  let address: string[] = []
  if (province && isNull(province)) {
    address.push(province)
  }

  if (city && isNull(city)) {
    address.push(city)
  }

  if (district && isNull(district)) {
    address.push(district)
  }

  return address.length ? address.join(separator) : defaultAddress
}

/**
 * 根据考核结果返回绩效等级
 *
 * @param score 考核结果
 * @returns
 */
export function scoreLevelByScore(score: number) {
  if (score > 90) {
    return 'A'
  } else if (score > 80 && score <= 90) {
    return 'B'
  } else if (score > 60 && score <= 80) {
    return 'C'
  } else {
    return 'D'
  }
}

/**
 * 字符转数字
 *
 * 会从字符中提取数字返回
 *
 * 如果字符中不包含数字，返回0
 *  */
export function str2num(val: string): number | undefined {
  let value = parseFloat((deepClone(val) as string).replace(/[^0-9|\.|\-]{0,}/g, ''))
  return value === value ? value : undefined
}

/**数字四舍五入 */
export function numRound(val: number, zeroNum: number = 1) {
  return Math.round(val * Math.pow(10, zeroNum)) / Math.pow(10, zeroNum)
}

/**
 *
 * @param val 传入的需要保留位数的字符或者数字
 * @param zeroNum 保留位数
 * @param overOmit 在补零阶段只补一个零，即时最终小数位并不会达到zeroNum的长度
 * @returns 补零完成后的字符
 */
export function zeroize(
  val: string | number,
  zeroNum: number = 1,
  overOmit: boolean = false
): string {
  let value: number | undefined = undefined

  if (typeof val === 'string') {
    value = str2num(val)
  } else {
    value = val
  }

  if (value !== 0 && !value) return ''

  let returnData = numRound(value, zeroNum)

  let numStr = returnData + ''

  let numStrArr = numStr.split('.') || []

  let intArr = (numStrArr[0] || '').split('')

  let decimalsArr = (numStrArr[1] || '').split('')

  let decimalsLen = decimalsArr.length

  if (decimalsLen === zeroNum) {
    return returnData + ''
  } else {
    // 补零操作
    let decimalsStr = decimalsArr.join('').padEnd(overOmit ? 1 : zeroNum - decimalsLen, '0')

    let intStr = intArr.join('')

    return intStr + '.' + decimalsStr
  }
}

/**
 * 文本换行符替换
 * 将输入的文本中的换行符,替换成/n字符
 *
 */
export function replaceBreak(str: string) {
  return str.replace(/(\n)+/g, '\\' + 'n')
}

export function unReplaceBreak(str: string | undefined | null) {
  return str ? str.replace(/\\n/g, '\n') : ''
}

/**
 * 校验区间字符是否输入正确
 */
export function checkRangeValue(range: string) {
  if (!range) return false
  let unitReg = /(\d+\-\d+)|(<=\d+)|(>=\d+)/

  return unitReg.test(range)
}

/**
 * 校验数字是否在区间字符的范围之间
 */
export function checkValueIsInRange(value: number, range: string) {
  if (!checkRangeValue(range)) return false

  let rangeArr = range
    .replace(/\-|(<=)|(>=)/, '$rangeUnit$')
    .split('$rangeUnit$')
    .map(item => str2num(item))
  if (rangeArr[0] === undefined || rangeArr[1] === undefined) return false

  if (range.indexOf('-') !== -1) {
    return value >= rangeArr[0] && value <= rangeArr[1]
  } else if (range.indexOf('<=') !== -1) {
    return value <= rangeArr[1]
  } else if (range.indexOf('>=') !== -1) {
    return value >= rangeArr[1]
  } else {
    console.error('范围解析失败')
    return false
  }
}

export function checkIsPhone() {
  const userAgent = navigator.userAgent.toLowerCase()
  const isMobile = /mobile|android|iphone|ipad|phone/i.test(userAgent)

  if (isMobile) {
    console.log('This is a mobile device')
    return true
  } else {
    console.log('This is not a mobile device')
    return false
  }
}
